<html><head><title>Memory Game</title>
<style type="text/css">
<!--
@import url('lslua.css');
//-->
</style>
</head><body>
Copy the code below and save it.
<h1>memory.lua</h1>
<pre><code>--[[ a "memory" game, implemented in lua and xlabel
  to run set

Include "path/to/file/memory.rc"
*Luafile "path/to/file/memory.lua"

and click Play! to play :-)
]]--
require "lsmodule"
require "evar"
module ("memory", package.seeall)

--- states to make sure the game doesnt start twice etc.
local NOT_STARTED = 0
local RUNNING = 1

-- the colors
local colors = { "#FF8000","#B35A00","#0066B3","#BFE4FF","#990099","#FF80FF","#CCFF00","#7A9900"}
-- copy the colors so we have each color twice ... these are the pairs
for i=1,#colors do
	table.insert(colors, colors[i])
end

--- shuffle the colors ... init the random
math.randomseed(os.time())
math.random() -- the first random number is not random ... yeah, dont ask ;-)
---simple shuffle function
function shuffle( t )
	local h
	local function swap(i,j) h=t[i] t[i] = t[j] t[j]=h end
	for i=1, #t do
		swap(i, math.random(i,#t))
	end
end

--- the game class
game = { state = NOT_STARTED}

--the Card class
local Card = {}

--- create the playfield
function game:init()
	self.state = NOT_STARTED
	self.score = lsmodule.xlabel.score -- the label to update
	self.turns = 0 -- how many turns
	self.lastcard = nil --last card drawn
	self.cards = {}
	self.pairs_left = 8 -- so we can find out when the game is over
	shuffle(colors) -- shuffle the colors
	self.score:create() -- create the label to display the score
	local xl, obj
	for k=0, 3 do -- 4 rows
		for i=0, 3 do -- 4 columns
			xl = lsmodule.xlabel[lsmodule.getname()] -- new label
			obj = Card:new( xl ) -- make a new Card instance
			obj.color = colors[1+(4*k+i)] -- assign a color
			xl.addtogroup = "card" -- some basic looks
			xl.x = 450 + i*100 --- positioning
			xl.y = 250 + k*100
			xl.onleftclick = lsmodule.callback( game.draw, game, obj) -- when a card is clicked do game:draw(card)
			xl:create() -- create the label.
			table.insert(game.cards, obj) -- save it for later when we destroy it again
		end
	end
end

function game:stop()
	self.state = NOT_STARTED
	for i,v in ipairs(self.cards) do 
		v.__xlabel__:destroy() -- destroy all the cards
	end
	self.score:destroy() -- destroy the scoreboard
end

--- create the game
function game:start()
	if self.state == NOT_STARTED then
		self:init() -- init the game
		self.state = RUNNING
	end
end

function game:won()
	lslua.message_box("Congratulations, you won the game in " .. self.turns .. " Turns!", "Memory")
	self:stop()
end

function game:draw( card )
	if card ~= self.lastcard then
		self.turns = self.turns +1
		self.score:settext( "Turns: " .. tostring( self.turns ))
		card:turn()
		if self.lastcard then -- there is a unmatched card laying open
			if self.lastcard.color == card.color then -- we hit a pair
				self.lastcard:finished() -- stop the cards from doing anything further
				card:finished()
				self.pairs_left = self.pairs_left-1 -- one pairs less to find
				if self.pairs_left == 0 then
					return self:won() -- no more pairs, we won
				end
				self.lastcard = nil -- the last card was in a pair, so we dont need it anymore
			else -- no match ... turn the old card around
				self.lastcard:turnback() 
				self.lastcard = card
			end
		else
			self.lastcard = card
		end
	end
end

function Card:turn() -- show a card
	self.__xlabel__:settext("")
	self.__xlabel__:refresh("colors", self.color)
end
function Card:turnback() -- hide it again
	self.__xlabel__:settext("?")
	self.__xlabel__:refresh("colors", evar.cardcolors)
end

function Card:finished() -- the pair was found, clicking it does nothing anymore
	self.__xlabel__.onleftclick = nil
end

function Card:new( xlabel ) -- Card class __init__ method.
	local obj = {}
	setmetatable(obj, self)
	self.__index =self
	obj.__xlabel__ = xlabel
	return obj
end
</code></pre>
<h1>memory.rc</h1><pre><code class="ls">cardpaintingmode ".singlecolor"
cardfontheight 40
cardwidth 90
cardheight 90
cardtext "?"
cardcolors  "#777777"

*label start
startpaintingmode ".singlecolor"
starttext "Play Memory!"
startonleftclick !luaexec memory.game:start()
startcolors "#E6F4FF"
startwidth 90
startheight 30
startx 450
starty $250-40$

scorepaintingmode ".singlecolor"
scoretext "Turns: 0"
scorecolors "#E6F4FF"
scorewidth 90
scoreheight 30
scorex $450+100$
scorey $250-40$


</code></pre></body></html>